﻿using System.Reflection;
using System.Text.RegularExpressions;

namespace Jim.SHR;

public class SHRClient:SdkClient
{

    /// <summary>
    /// 登录用户名
    /// </summary>
    private string UserName { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    private string Password { get; set; }

    /// <summary>
    /// 
    /// </summary>
    private string SlnName { get; set; }
    /// <summary>
    /// 数据中心名称
    /// </summary>
    private string DcName { get; set; }
    /// <summary>
    /// 语言
    /// </summary>
    private string Language { get; set; }

    /// <summary>
    /// 数据库类型
    /// </summary>
    private int DbType { get; set; }

    public WSContext Context { get; set; }
    /// <summary>
    /// 最后登录时间
    /// </summary>
    private DateTime _sessionTime = new DateTime(1900, 1, 1);

    /// <summary>
    /// 登录时长
    /// </summary>
    private double DateDif => (DateTime.Now - _sessionTime).TotalMilliseconds;


    #region 构造函数

    public SHRClient(string url, string userName, string password, string slnName, string dcName,string language,int dbType =0)
    {
        ServerUrl = url;
        UserName = userName;
        Password = password;
        SlnName = slnName;
        DcName = dcName;
        Language = language;
        DbType = dbType;
    }

    #endregion


    public override async Task<T> Execute<T>(ISdkRequest<T> request)
    {
        SdkAttribute oaReqAttr = request.GetType().GetCustomAttribute<SdkAttribute>();
        if (oaReqAttr == null)
            return Error<T>("Input对象缺少SdkAttribute属性，请联系管理员");

        if ( DateDif >= 175)
        {
            Context = await Login();
            _sessionTime = DateTime.Now;
        }

        // 数据请求
        string json = string.Empty;
        try
        {
            var queryData = BuildPostData(request);
            Log($"请求数据:{queryData}");
            //适配http1.0，处理SHR报错
            System.Net.ServicePointManager.Expect100Continue = false;
            //初始化SHR服务
            WSOSFWebserviceFacadeSrvProxyClient service = new WSOSFWebserviceFacadeSrvProxyClient() { };
            //调用结果
            var response =  await service.proceedOSFAsync(oaReqAttr.Url, queryData);
            json = response.proceedOSFReturn;
            Log($"返回信息:{json}");
        }
        catch (Exception e)
        {
            return Error<T>($"网络请求失败:{e.Message}");
        }

        // 数据解析
        T rsp = BuildResponse<T>(request,json);
        Log($"解析后:{rsp.ToJson()}");
        return rsp;
    }

    #region 解析返回值



    /// <summary>
    /// 返回对象处理
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    protected override T BuildResponse<T>(ISdkRequest request, string value)
    {
        JToken jToken =null;
        try
        {
            // 尝试进行JSon反序列化
            jToken = JToken.Parse(value);
            // 如果不是对象类型，直接返回
            if (jToken.Type != JTokenType.Object)return Success<T>( jToken);
        }
        catch // 反序列化不成功
        {
            // 用正则判断是否包含json
            Regex regex = new Regex(@"{.*?}$"); // 假设只想提取大括号之间的部分
            Match match = regex.Match(value);
            if (match.Success)//如果包含json，则判断服务器返回错误信息
            {
                string json = match.Value;
                var exception = json.FromJson<SdkServiceException>();
                return Error<T>( $"云星空服务器内部错误:{exception.Source}/{exception.Message}");
            }
            else
            {
                // 如果不包含json则直接跳过
                return Success<T>( value);
            }
        }

        bool isSuccess = true;
        string errMessage = "";
        JToken dataToken = null;

        JToken responseStatusToken = null;
        JToken resultResultToken = null;
        JToken paramsToken = null;

        jToken.TryGetToken("Result", out JToken resultToken, true);
        jToken.TryGetToken("Successful", out JToken successfulToken, true);
        jToken.TryGetToken("Message", out JToken messageToken, true);
        jToken.TryGetToken("actionname", out JToken activeNameToken, true);

        if (successfulToken != null) isSuccess = successfulToken.Value<bool>();
        if (messageToken != null) errMessage += messageToken.Value<string>();
        if (dataToken == null) 
            dataToken = jToken;
        return Success<T>( dataToken);

    }

    #endregion

    #region Token处理
    public async Task<WSContext> Login()
    {
        System.Net.ServicePointManager.Expect100Continue = false;
        EASLoginProxyClient service = new EASLoginProxyClient();
        loginResponse response = await service.loginAsync(UserName, password: Password, SlnName,  DcName, Language, DbType);
        return response.loginReturn;
    }

    public async Task<bool> Logout()
    { 
        System.Net.ServicePointManager.Expect100Continue = false;
        EASLoginProxyClient service = new EASLoginProxyClient();
        logoutResponse response = await service.logoutAsync(UserName, SlnName, DcName,Language);
        return response.logoutReturn;
    }

    #endregion

}
